package com.ziytek.web.citizen.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serial;
import java.nio.charset.StandardCharsets;

/**
 * @author fenghx
 * @version 1.0
 * @className AESSecureKey
 * Description:
 * @date 2024/3/12 11:02
 */
@Slf4j
public class AESSecureKey implements SecureKey {
    /**
     *
     */
    @Serial
    private static final long serialVersionUID = 1548468812956018732L;
    private static final String AES_NAME = "AES";
    private static final String AES_MODEL = "AES/ECB/PKCS5Padding";
    private transient Cipher eCipher;
    private transient Cipher dCipher;
    private final String password;

    public AESSecureKey(String password) {
        this.password = password;
    }

    @Override
    public String encrypt(String original) {
        if (StringUtil.isEmpty(original)) {
            return "";
        }
        try {
            initCipher();
            return new String(Base64.encodeBase64(eCipher.doFinal(original.getBytes())));
        } catch (Exception e) {
            log.error(String.format("对称密钥加密失败---->[%s]", e.getMessage()), e);
            return "";
        }
    }

    @Override
    public String decrypt(String original) {
        if (StringUtil.isEmpty(original)) {
            return "";
        }
        try {
            initCipher();
            return new String(dCipher.doFinal(Base64.decodeBase64(original.getBytes())));
        } catch (Exception e) {
            log.error(String.format("对称密钥解密失败---->errMsg[%s] original[%s]", e.getMessage(), original), e);
            return "";
        }
    }

    private void initCipher() throws Exception {
        if (eCipher != null || dCipher != null) {
            return;
        }
        synchronized (this) {
            if (eCipher != null || dCipher != null) {
                return;
            }
            SecretKeySpec sKeySpec = new SecretKeySpec(password.getBytes(StandardCharsets.UTF_8), AES_NAME);
            // "算法/模式/补码方式"
            eCipher = Cipher.getInstance(AES_MODEL);
            eCipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
            // "算法/模式/补码方式"
            dCipher = Cipher.getInstance(AES_MODEL);
            dCipher.init(Cipher.DECRYPT_MODE, sKeySpec);
        }
    }

    @Override
    public String getName() {
        return AES_NAME;
    }
}
